﻿using System.Windows.Forms;
using CommonLibrary;
using InputManager.InputHooks;
using InputManager.View;

namespace InputManager.InputHandlers
{
    class InputHandler
    {
        private readonly FinalProcessor _finalProcessor;
        private readonly CalibrationProcessor _featureProcessor;
        private readonly SpecialProcessor _specialProcessor;
        
        public InputHandler(IAppContext context)
        {
            _featureProcessor = new CalibrationProcessor(context);
            _finalProcessor = new FinalProcessor(context);
            _specialProcessor = new SpecialProcessor(context);
        }

        public void Start(InputWindow inputWindow)
        {
            inputWindow.RawInputDevice.KeyDown += KeyboardHookKeyDown;
            inputWindow.RawInputDevice.KeyUp += KeyboardHookKeyUp;
            inputWindow.RawInputDevice.MouseButtonDown += MouseHookMouseDown;
            inputWindow.RawInputDevice.MouseButtonUp += MouseHookMouseUp;
            inputWindow.RawInputDevice.MouseWheel += MouseHookMouseWheel;
            inputWindow.RawInputDevice.MouseMove += MouseHookMouseMove;
        }

        // Events
        //TODO refactor so that there is only one check for each key/mouse event
        // this should partially reduce the load on the PC, as it is now multiple events can be triggerd / ms using high end mouse and keyboards

        void KeyboardHookKeyUp(object sender, RawInputHook.KeyControlEventArgs controlEventArgs)
        {
            if (controlEventArgs.Keyboard == null) return;
            
            if (_featureProcessor.ValidateInput(InputType.KeyUp, controlEventArgs.Keyboard.key)) return;
            if (_specialProcessor.ValidateInput(InputType.KeyUp, controlEventArgs.Keyboard.key)) return;
            _finalProcessor.KeyUp((Keys) controlEventArgs.Keyboard.key);
        }

        void KeyboardHookKeyDown(object sender, RawInputHook.KeyControlEventArgs controlEventArgs)
        {
            if (controlEventArgs.Keyboard == null) return;

            if (_featureProcessor.ValidateInput(InputType.KeyDown, controlEventArgs.Keyboard.key)) return;
            if (_specialProcessor.ValidateInput(InputType.KeyDown, controlEventArgs.Keyboard.key)) return;
            _finalProcessor.KeyDown((Keys) controlEventArgs.Keyboard.key);
        }

        void MouseHookMouseWheel(object sender, MouseEventArgs mouseEventArgs)
        {
            if (_featureProcessor.ValidateInput(InputType.MouseWheel, mouseEventArgs.Delta)) return;
            if (_specialProcessor.ValidateInput(InputType.MouseWheel, mouseEventArgs.Delta)) return;
            _finalProcessor.MouseWheel(mouseEventArgs.Delta);
        }

        void MouseHookMouseUp(object sender, MouseEventArgs mouseEventArgs)
        {
            if (_featureProcessor.ValidateInput(InputType.MouseUp, mouseEventArgs.Button)) return;
            if (_specialProcessor.ValidateInput(InputType.MouseUp, mouseEventArgs.Button)) return;
            _finalProcessor.MouseButtonUp(mouseEventArgs.Button);
        }

        void MouseHookMouseDown(object sender, MouseEventArgs mouseEventArgs)
        {
            if (_featureProcessor.ValidateInput(InputType.MouseDown, mouseEventArgs.Button)) return;
            if (_specialProcessor.ValidateInput(InputType.MouseDown, mouseEventArgs.Button)) return;
            _finalProcessor.MouseButtonDown(mouseEventArgs.Button);
        }

        void MouseHookMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            if (_featureProcessor.ValidateInput(InputType.MouseMove, mouseEventArgs.Location)) return;
            if (_specialProcessor.ValidateInput(InputType.MouseMove, mouseEventArgs.Location)) return;
            _finalProcessor.MouseMoved(mouseEventArgs.Location);
        }
    }
}